<?php

namespace App\Logic;

use App\Model\ActivityApplyModel;
use App\Model\ActivityModel;
use App\Model\ActivitySignModel;
use EasySwoole\Http\Message\Status;
use EasySwoole\Mysqli\QueryBuilder;
use EasySwoole\ORM\Db\ClientInterface;
use EasySwoole\ORM\DbManager;
use EasySwoole\ORM\Exception\Exception;
use EasySwoole\Pool\Exception\PoolEmpty;
use EasySwoole\Pool\Manager;
use Throwable;

class SignLogic
{
    /**
     * 打卡签到处理
     * @param $userId
     * @param $activityId
     * @return array
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    public static function addUserSignHandle($userId, $activityId)
    {
        $activity = DbManager::getInstance()->invoke(function ($client) use ($activityId) {
            return ActivityModel::invoke($client)->findActivity($activityId);
        });
        if ($activity['status'] != 1) {
            return [
                "code" => Status::CODE_BAD_REQUEST,
                "result" => [],
                "msg" => "该活动不存在"
            ];
        }

        // 当前时间小于赛事开始时间，不让打卡
        if (strtotime($activity['start_date'] . ' ' . $activity['start_time']) > time()) {
            return [
                "code" => Status::CODE_BAD_REQUEST,
                "result" => [],
                "msg" => "赛事还没有开始"
            ];
        }

        // 当前时间大于赛事结束时间，不让打卡
        if (time() > strtotime($activity['end_date'] . ' ' . $activity['end_time'])) {
            return [
                "code" => Status::CODE_BAD_REQUEST,
                "result" => [],
                "msg" => "赛事已经结束"
            ];
        }

        // 当前时间不在打卡时间段以内的话，不让打卡
        if (time() < strtotime(date('Y-m-d ' . $activity['start_time'])) || time() > strtotime(date('Y-m-d ' . $activity['end_time']))) {
            return [
                "code" => Status::CODE_BAD_REQUEST,
                "result" => [],
                "msg" => "不在打卡时间段内"
            ];
        }

        // 查询该用户是否报名该赛事
        $apply = DbManager::getInstance()->invoke(function ($client) use ($userId, $activityId) {
            return ActivityApplyModel::invoke($client)
                ->changeTableName($userId)
                ->where('user_id', $userId)
                ->where('activity_id', $activityId)
                ->get();
        });
        if (!$apply) {
            return [
                "code" => Status::CODE_BAD_REQUEST,
                "result" => [],
                "msg" => "没有报名该活动赛事"
            ];
        }

        // 查询该用户是否当天已经打卡
        $sign = DbManager::getInstance()->invoke(function ($client) use ($userId, $activityId) {
            return ActivitySignModel::invoke($client)
                ->changeTableName($userId)
                ->where('user_id', $userId)
                ->where('activity_id', $activityId)
                ->where('LEFT(`sign_datetime`, 10)', date('Y-m-d'))
                ->get();
        });
        if ($sign) {
            return [
                "code" => Status::CODE_BAD_REQUEST,
                "result" => [],
                "msg" => "已经签到了"
            ];
        }

        return DbManager::getInstance()->invoke(function (ClientInterface $client) use ($userId, $activityId, $apply) {
            try {
                // 开启事务
                DbManager::getInstance()->startTransaction($client);

                // 插入打卡记录
                ActivitySignModel::invoke($client)->changeTableName($userId)->data([
                    'user_id' => $userId,
                    'activity_id' => $activityId,
                ], false)->save();

                // 申请记录签到次数+1
                ActivityApplyModel::invoke($client)->changeTableName($userId)->update([
                    'sign_time' => QueryBuilder::inc(1),
                    'status' => ($apply->target_time == ($apply->sign_time + 1) ? 1 : $apply->status),
                    'update_time' => time(),
                ], ['id' => $apply->id]);

                // 加入Redis的列表
                go(function () use ($activityId, $userId) {
                    $redis = Manager::getInstance()->get('redis')->getObj();
                    $redisKeyName = 'list_' . $activityId . '_' . date('Ymd');
                    $redis->lPush($redisKeyName, $userId);
                    Manager::getInstance()->get('redis')->recycleObj($redis);
                });
            } catch (Throwable  $e) {
                // 回滚事务
                DbManager::getInstance()->rollback($client);
                return [
                    "code" => Status::CODE_BAD_GATEWAY,
                    "result" => [],
                    "msg" => "网络繁忙,请稍后再试"
                ];
            } finally {
                // 提交事务
                DbManager::getInstance()->commit($client);
                return [
                    "code" => Status::CODE_OK,
                    "result" => [],
                    "msg" => "签到成功"
                ];
            }
        });
    }
}